use std::collections::HashMap;

fn main() {
    // Creating a New Hash Map
    let mut scores = HashMap::new();

    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Red"), 50);

    // Accessing Values in a Hash Map
    let tea_name = String::from("Blue");
    let score = scores.get(&tea_name).copied().unwrap_or(0);

    println!("tea_name: {tea_name} score:{score}");

    for (key, value) in &scores {
        println!("{key}: {value}");
    }

    // Hash Maps and Ownership
    let field_name = String::from("Favorite color");
    let field_value = String::from("Blue");

    let mut map = HashMap::new();
    map.insert(&field_name, &field_value);
    for (key, value) in &map {
        println!("{key}: {value}");
    }

    // field_name and field_value are invalid at this point, try using them and
    // see what compiler error you get!
    // map.insert(field_name, field_value);
    // println!("field_name: {field_name} field_value:{field_value}" );

    // Overwriting a Value
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Blue"), 25);
    println!("{scores:?}");

    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.entry(String::from("Yellow")).or_insert(50);
    scores.entry(String::from("Blue")).or_insert(50); // 返回 value 的可变引用
    println!("{scores:?}");
    scores.insert(String::from("Blue"), 80);
    println!("{scores:?}");

    // Updating a Value Based on the Old Value
    let text = "hello world wonderful world";
    let mut map = HashMap::new();
    for word in text.split_whitespace() {
        let count = map.entry(word).or_insert(0);
        *count += 1;
    }
    println!("{map:?}");

    // exercices
    // Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company;
    // for example, “Add Sally to Engineering” or “Add Amir to Sales.” Then let the user retrieve a list of all people in a department or all people
    // in the company by department, sorted alphabetically.

    // <department<users>>
    let mut departments: HashMap<String, Vec<String>> = HashMap::new();
    addUser2Department(
        String::from("zhangsan"),
        String::from("IT"),
        &mut departments,
    );
    addUser2Department(String::from("lisi"), String::from("UE"), &mut departments);
    addUser2Department(String::from("wea"), String::from("IT"), &mut departments);
    addUser2Department(String::from("oo"), String::from("UE"), &mut departments);
    addUser2Department(String::from("as"), String::from("IT"), &mut departments);
    addUser2Department(String::from("ddd"), String::from("PP"), &mut departments);
    printAllDepartment(&departments);
    addUser2Department(String::from("aa"), String::from("UE"), &mut departments);
    addUser2Department(String::from("ad"), String::from("IT"), &mut departments);
    addUser2Department(String::from("fd"), String::from("PP"), &mut departments);
    printAllDepartment(&departments);
}

fn printAllDepartment(de: &HashMap<String, Vec<String>>) {
    for (key, value) in de {
        print!("{key} has: ");
        for name in value {
            print!("{name} ");
        }
        println!("");
    }
}

fn addUser2Department(
    name: String,
    department: String,
    departments: &mut HashMap<String, Vec<String>>,
) {
    for (key, value) in &mut *departments {
        if department == *key {
            value.push(name.clone());
            return;
        }
    }
    let mut de: Vec<String> = vec![];
    de.push(name);
    departments.insert(department, de);
}
